package com.shiguiwu.springboot3.processor;

import com.google.auto.service.AutoService;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Names;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import java.util.Set;

/**
 * @description: 注解处理器
 * @author: stone
 * @date: Created by 2023/12/1 20:04
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springboot3.processor
 */
@SupportedAnnotationTypes("com.shiguiwu.springboot3.processor.MyAnnotation")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@AutoService(Processor.class)
public class MyProcessor  extends AbstractProcessor {

    private JavacTrees javacTrees; // 提供了待处理的抽象语法树
    private TreeMaker treeMaker; // 封装了创建AST节点的一些方法
    private Names names; // 提供了创建标识符的方法

    /**
     * 从Context中初始化JavacTrees，TreeMaker，Names
     */
    //@Override
    //public synchronized void init(ProcessingEnvironment processingEnv) {
    //    super.init(processingEnv);
    //    Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
    //    javacTrees = JavacTrees.instance(processingEnv);
    //    treeMaker = TreeMaker.instance(context);
    //    names = Names.instance(context);
    //}
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        final JavacElements elementUtils = (JavacElements) processingEnv.getElementUtils();
        final Context context = ((JavacProcessingEnvironment) processingEnv).getContext();
        final TreeMaker treeMaker = TreeMaker.instance(context);

        // 返回使用给定注释类型注释的元素的集合。
        Set<? extends Element> elementsAnnotatedWith = roundEnv.getElementsAnnotatedWith(MyAnnotation.class);
        for (Element element : elementsAnnotatedWith) {
            // 获取当前类的抽象语法树
            JCTree.JCMethodDecl jcMethodDecl = (JCTree.JCMethodDecl) elementUtils.getTree(element);

            treeMaker.pos = jcMethodDecl.pos;
            jcMethodDecl.body = treeMaker.Block(0, List.of(
                    treeMaker.Exec(
                            treeMaker.Apply(
                                    List.<JCTree.JCExpression>nil(),
                                    treeMaker.Select(
                                            treeMaker.Select(
                                                    treeMaker.Ident(
                                                            elementUtils.getName("System")
                                                    ),
                                                    elementUtils.getName("out")
                                            ),
                                            elementUtils.getName("println")
                                    ),
                                    List.<JCTree.JCExpression>of(
                                            treeMaker.Literal("Hello, world!!!")
                                    )
                            )
                    ),
                    jcMethodDecl.body
            ));
        }
        return true;
    }
}
